﻿#include "KuGouMusicManager.h"

#include<qnetworkaccessmanager.h>
#include<qnetworkreply.h>
#include<qnetworkrequest.h>
#include<qjsonarray.h>
#include<qjsonobject.h>
#include<qjsondocument.h>
#include<qjsonvalue.h>
#include<Song.h>
#include<qfile.h>
#include<qdir.h>
#include<memory>

KuGouMusicManager::KuGouMusicManager(std::unique_ptr<KuGouApi> apiSource, QObject* parent):QObject(parent)
{
	m_api = std::move(apiSource);
	m_manager = new QNetworkAccessManager(this);
}

KuGouMusicManager::KuGouMusicManager(const JsonKeysConfig& config, 
	std::unique_ptr<KuGouApi> apiSource, 
	QObject* parent
):m_config(config)	
{
		m_api = std::move(apiSource);
	m_manager = new QNetworkAccessManager(this);
}

KuGouMusicManager::KuGouMusicManager()
{
}

void KuGouMusicManager::searchSong(
	const JsonKeysConfig& retJsonKeys,
	const QString& songName, 
	int pageSize, 
	int page
){
	QString getUrl = m_api->searchSongs(songName, page, pageSize);
	
	QNetworkRequest request(getUrl);
	QNetworkReply* reply =  m_manager->get(request);
	if (!m_replies.contains(reply))
	{
		m_replies.push_back(reply);
	}
	
	connect(reply, &QNetworkReply::finished, 
		[this,reply,retJsonKeys]() {
			if (m_replies.contains(reply))
			{
				m_replies.removeOne(reply);
			}

			if (reply->error() == QNetworkReply::NoError)
			{
				QByteArray songsData = reply->readAll();
				QJsonParseError parseError;
				auto songs_doc=  QJsonDocument::fromJson(songsData,&parseError);
				//正确解析
				const auto parentKeys = retJsonKeys.getParentKeys();
				if (parseError.error == QJsonParseError::NoError)
				{
					
					//解析Json
					QJsonObject jsonObj = songs_doc.object();
					//进入倒数第二次，musicList的那一层
					for (int i = 0; i < parentKeys.size() - 1; i++)
					{
						auto& key = parentKeys[i];
						if (jsonObj.contains(key))
						{
							//进入下一层
							jsonObj = jsonObj[key].toObject();
						}
						else
						{
							qWarning() << "没有key = " << key;
						}
					}

					auto last = jsonObj[parentKeys.last()];
					//音乐数组信息
					if (last.isArray())
					{
						QList< OnlionMusicInfo> info_list;
						OnlionMusicInfo info;
						auto songsInfo = last.toArray();
						auto songKeys = retJsonKeys.getSongKeys();
						for (int i = 0; i < songsInfo.count(); i++)
						{
							if (songsInfo[i].isObject()) 
							{
								auto obj = songsInfo[i].toObject();
								
								info.songName= obj[songKeys[SongKeys::SongName]].toString();
								info.songHash = obj[songKeys[SongKeys::SongHash]].toString();
								info.singerName = obj[songKeys[SongKeys::SingerName]].toString();
								info.songExtname = obj[songKeys[SongKeys::Extname]].toString();
								info.duration_s = QString::number(obj[songKeys[SongKeys::Duration_s]].toInt());
								//info.payType = QString::number(obj[songKeys[SongKeys::Pay_type]].toInt());
								//info.url = this->getSongUrl;
								info_list.push_back(info);
							}
							else
							{
								qWarning("songsInfo[%d] isn't object", i);
							}
						}
						emit searchFinished(std::move(info_list));
						
					}
					else
					{
						qWarning() << parentKeys[parentKeys.size() - 1] << "isn't Key of Array";
					}
					
					

				}
				else
				{
					qWarning() << "error parsing Json : " << parseError.errorString();
				}
				
			}
			else
			{
				qDebug() << "get Error： " << reply->errorString();
			}


			reply->deleteLater();
		});
	
}




void KuGouMusicManager::searchSong(const JsonKeysConfig& retJsonKeys, 
	const JsonKeysConfig& urlRetJsonKeys, const QString& songName, int pageSize, int searchPage)
{
	QString getUrl = m_api->searchSongs(songName,searchPage,pageSize);

	QNetworkRequest request(getUrl);
	QNetworkReply* reply = m_manager->get(request);
	if (!m_replies.contains(reply))
	{
		m_replies.push_back(reply);
	}

	connect(reply, &QNetworkReply::finished,
		[this, reply, retJsonKeys,urlRetJsonKeys]() {
			if (m_replies.contains(reply))
			{
				m_replies.removeOne(reply);
			}

			if (reply->error() == QNetworkReply::NoError)
			{
				QByteArray songsData = reply->readAll();
				QJsonParseError parseError;
				auto songs_doc = QJsonDocument::fromJson(songsData, &parseError);
				//正确解析
				const auto parentKeys = retJsonKeys.getParentKeys();
				if (parseError.error == QJsonParseError::NoError)
				{

					//解析Json
					QJsonObject jsonObj = songs_doc.object();
					//进入倒数第二次，musicList的那一层
					for (int i = 0; i < parentKeys.size() - 1; i++)
					{
						auto& key = parentKeys[i];
						if (jsonObj.contains(key))
						{
							//进入下一层
							jsonObj = jsonObj[key].toObject();
						}
						else
						{
							qWarning() << "没有key = " << key;
						}
					}

					auto last = jsonObj[parentKeys.last()];
					//音乐数组信息
					if (last.isArray())
					{
						QList< OnlionMusicInfo> info_list;
						OnlionMusicInfo info;
						auto songsInfo = last.toArray();
						auto songKeys = retJsonKeys.getSongKeys();
						QList<QString> hashList;
						for (int i = 0; i < songsInfo.count(); i++)
						{
							if (songsInfo[i].isObject())
							{
								auto obj = songsInfo[i].toObject();

								info.songName = obj[songKeys[SongKeys::SongName]].toString();
								info.songHash = obj[songKeys[SongKeys::SongHash]].toString();
								info.singerName = obj[songKeys[SongKeys::SingerName]].toString();
								info.songExtname = obj[songKeys[SongKeys::Extname]].toString();
								info.duration_s = QString::number(obj[songKeys[SongKeys::Duration_s]].toInt());
								//info.payType = QString::number(obj[songKeys[SongKeys::Pay_type]].toInt());
								//info.url = this->getSongUrl;
								info_list.push_back(info);
								hashList.push_back(info.songHash);
							}
							else
							{
								qWarning("songsInfo[%d] isn't object", i);
							}
						}
						emit searchFinished(std::move(info_list));
						getSongUrl(urlRetJsonKeys, hashList);
					}
					else
					{
						qWarning() << parentKeys[parentKeys.size() - 1] << "isn't Key of Array";
					}



				}
				else
				{
					qWarning() << "error parsing Json : " << parseError.errorString();
				}

			}
			else
			{
				qDebug() << "get Error： " << reply->errorString();
			}

			reply->deleteLater();
		});
}

void KuGouMusicManager::searchSong(const QString& songName, int pageSize, int searchPage)
{
	this->searchSong(m_config, songName, pageSize, searchPage);
}

void KuGouMusicManager::setJsonKeysConfig(const JsonKeysConfig& config)
{
	m_config = config;
}

void KuGouMusicManager::getSongUrl(const JsonKeysConfig retJsonKeys, const QString songHash)
{
	QUrl urlGet = m_api->getMusic(songHash);
	QNetworkRequest request(urlGet);

	QNetworkReply* reply = m_manager->get(request);

	for (auto& i : m_replies)
	{
		i->abort();
	}
	if (!m_replies.contains(reply))
	{
		m_replies.push_back(reply);
	}

	connect(reply, &QNetworkReply::finished, this,
		[this, retJsonKeys,reply]() {
			if (reply->error() == QNetworkReply::NoError)
			{
				if (m_replies.contains(reply))
				{
					m_replies.removeOne(reply);
				}
				QByteArray data = reply->readAll();
				QJsonParseError parseError;
				QJsonDocument doc =  QJsonDocument::fromJson(data,&parseError);
				if (parseError.error == QJsonParseError::NoError)
				{
					QJsonObject jsonObj = doc.object();
					const auto& parentKeys = retJsonKeys.getParentKeys();
					for (auto& i : parentKeys)
					{
						if (jsonObj.contains(i))
						{
							jsonObj = jsonObj[i].toObject();
						}
						else
						{
							qWarning() << __FUNCTION__ << "error: don't contain " << i;
							
						}
					}

					//...
					const auto& keys = retJsonKeys.getSongKeys();
					Song s;
					s.duration_s = jsonObj[keys[SongKeys::Duration_s]].toInt();
					s.singerName = jsonObj[keys[SongKeys::SingerName]].toString();
					s.songName = jsonObj[keys[SongKeys::SongName]].toString();
					s.type = jsonObj[keys[SongKeys::Extname]].toString();
					emit this->getUrl(jsonObj[keys[SongKeys::Url]].toString());
				}
				else
				{
					qWarning() << "parse getSong Url Error: " << parseError.errorString();
				}
			}
			else
			{
				qWarning() << "getSongUrl error";
			}

			reply->deleteLater();
		});

}


void KuGouMusicManager::getSongUrl(const JsonKeysConfig retJsonKeys, const QStringList hashList)
{
	//多线程执行计数
	auto counter = std::make_shared<int>(0);

	auto size = hashList.size();
	auto urlList = std::make_shared<QList<QUrl>>(size);

	for (auto& i : m_replies)
	{
		i->abort();
	}
	

	for (int i = 0; i < size; i++)
	{
		QUrl urlGet = m_api->getMusic(hashList[i]);
		QNetworkRequest request(urlGet);

		QNetworkReply* reply = m_manager->get(request);
		if (!m_replies.contains(reply))
		{
			m_replies.push_back(reply);
		}
		connect(reply, &QNetworkReply::finished, this,
			[=]() {

				if (m_replies.contains(reply))
				{
					m_replies.removeOne(reply);
				}
				if (reply->error() == QNetworkReply::NoError)
				{
					QByteArray data = reply->readAll();
					QJsonParseError parseError;
					QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);
					if (parseError.error == QJsonParseError::NoError)
					{
						QJsonObject jsonObj = doc.object();
						const auto& parentKeys = retJsonKeys.getParentKeys();
						for (auto& i : parentKeys)
						{
							if (jsonObj.contains(i))
							{
								jsonObj = jsonObj[i].toObject();
							}
							else
							{
								qWarning() << __FUNCTION__ << "error: don't contain " << i;

							}
						}

						//...
						const auto& keys = retJsonKeys.getSongKeys();
						Song s;
						s.hash = jsonObj[keys[SongKeys::SongHash]].toString();
						s.duration_s = jsonObj[keys[SongKeys::Duration_s]].toInt();
						s.singerName = jsonObj[keys[SongKeys::SingerName]].toString();
						s.songName = jsonObj[keys[SongKeys::SongName]].toString();
						s.type = jsonObj[keys[SongKeys::Extname]].toString();
						//emit this->getUrl(jsonObj[keys[SongKeys::Url]].toString());
						(*urlList)[i] = jsonObj[keys[SongKeys::Url]].toString();
						qDebug() << "key is" << keys[SongKeys::Url];
						qDebug() << "singerName is " << keys[SongKeys::SingerName];
						++(*counter);
					}
					else
					{
						qWarning() << "parse getSong Url Error: " << parseError.errorString();
					}
				}
				else
				{
					qWarning() << "getSongUrl error";
				}
				if (*counter == size)
				{
					emit getUrl(*urlList);
				}
				reply->deleteLater();
			});
	}
	
}

void KuGouMusicManager::downloadSong(QUrl url, const QString& singerName,const QString& songName,const QString& fileType)
{
	QDir dir;
	if (dir.mkpath("music/Online")) {
		qDebug() << "Success";
		QNetworkRequest request(url);
		QNetworkReply* reply = m_manager->get(request);
		connect(reply, &QNetworkReply::finished, this,
			[this,reply,singerName,songName,fileType]() {
				qDebug() << "正在下载";
				if (reply->error() != QNetworkReply::NoError) {
					qWarning() << "下载失败: " << reply->errorString();
					reply->deleteLater(); 
					return;
				}

				auto data = reply->readAll();
				if (data.isEmpty()) {
					qWarning() << "下载失败: 接收到的数据为空 (URL可能已失效)";
					reply->deleteLater();
					return;
				}

				QDir musicDir("music/Online");
				QString fullPath = musicDir.filePath(".tmp");
				QFile musicFile(fullPath);

				if (musicFile.open(QIODeviceBase::WriteOnly))
				{
					musicFile.write(data);
					musicFile.close();
					if (singerName.isEmpty())
					{
						musicFile.rename(musicDir.filePath(songName + "." + fileType) );
						
					}
					else
					{
						musicFile.rename(musicDir.filePath(songName + "-" + singerName + "." + fileType));
					}
					emit downloadSongFinished();
					
				}
				else
				{
					downloadSongFailed(musicFile.errorString());
				}

				reply->deleteLater();
			});
		
	}
	else
	{
		qWarning() << "creat failed";
	}
}

void KuGouMusicManager::setApi(std::unique_ptr<KuGouApi> apiSource)
{
	m_api = std::move(apiSource);
}
